﻿/*
 * Copyright (C) 2012, EADS France
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * Author: Laurent WOUTERS
 */

using System;
using System.Collections.Generic;
using System.Text;
using Hime.Redist.Parsers;

namespace xowl.gmi.compiler.view
{
    class IDProvider
    {
        private static System.Random rand = new Random();
        public static string GetID(string radical) { return radical + rand.Next().ToString(); }
    }

    interface Symbol
    {
        string Name { get; }
        void BuildDefaultModel(model.Model model, ViewDefinition view);
        ast.ASTPattern BuildASTPattern();
    }

    interface Value
    {
        string WriteOWL(System.IO.StreamWriter writer);
    }
    interface ValueInteger : Value { }
    interface ValueString : Value { }
    interface ValueColor : Value { }

    class ConstantInteger : ValueInteger
    {
        private int value;
        public ConstantInteger(SyntaxTreeNode node)
        {
            value = Int32.Parse((node.Symbol as SymbolTokenText).ValueText);
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("ci");
            writer.WriteLine("\tClassAssertion(cvssl:ConstantInteger :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:valueInt :" + id + " " + value + ")");
            return id;
        }
        public override string ToString() { return value.ToString(); }
    }
    class ConstantString : ValueString
    {
        private string value;
        public ConstantString(SyntaxTreeNode node)
        {
            value = (node.Symbol as SymbolTokenText).ValueText;
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("cs");
            writer.WriteLine("\tClassAssertion(cvssl:ConstantString :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:valueString :" + id + " " + value + ")");
            return id;
        }
        public override string ToString() { return value.ToString(); }
    }
    class ConstantColor : ValueColor
    {
        private int value;
        public ConstantColor(SyntaxTreeNode node)
        {
            value = Int32.Parse((node.Symbol as SymbolTokenText).ValueText.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier);
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("cs");
            writer.WriteLine("\tClassAssertion(cvssl:ConstantColor :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:valueColor :" + id + " " + value + ")");
            return id;
        }
        public override string ToString() { return "#"+value.ToString("X"); }
    }

    class Parameter : ValueInteger, ValueString, ValueColor
    {
        private string name;
        private string owlID;
        public string Name { get { return name; } }
        public string OWLID { get { return owlID; } }
        public Parameter(string name)
        {
            this.name = name;
            this.owlID = IDProvider.GetID("param");
        }
        public string WriteOWLDefinition(System.IO.StreamWriter writer)
        {
            writer.WriteLine("\tClassAssertion(cvssl:Parameter :" + owlID + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:name :" + owlID + " \"" + name + "\")");
            return owlID;
        }
        public string WriteOWL(System.IO.StreamWriter writer) { return owlID; }
        public override string ToString() { return "$" + name; }
    }

    class SizeInfo
    {
        private ValueInteger width;
        private ValueInteger height;
        private bool isFill;
        public SizeInfo(SyntaxTreeNode node, Variable variable)
        {
            width = variable.GetValueInteger(node.Children[0]);
            height = variable.GetValueInteger(node.Children[1]);
            isFill = node.Children.Count > 2;
        }
        public void WriteOWL(System.IO.StreamWriter writer, string id)
        {
            string wID = width.WriteOWL(writer);
            string hID = height.WriteOWL(writer);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:width :" + id + " :" + wID + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:height :" + id + " :" + hID + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isFill :" + id + " \"" + isFill.ToString().ToLower() + "\"^^xsd:boolean)");
        }
    }

    class DrawingInfo
    {
        private ValueColor fillColor;
        private ValueColor borderColor;
        private ValueInteger borderThickness;
        public DrawingInfo(SyntaxTreeNode node, Variable variable)
        {
            if (node.Children.Count == 0) return;
            if (node.Children[0].Children.Count != 0)
                fillColor = variable.GetValueColor(node.Children[0].Children[0]);
            if (node.Children[1].Children.Count == 0) return;
            borderColor = variable.GetValueColor(node.Children[1].Children[0]);
            if (node.Children[1].Children.Count == 1) return;
            borderThickness = variable.GetValueInteger(node.Children[1].Children[1]);
        }
        public void WriteOWL(System.IO.StreamWriter writer, string id)
        {
            if (fillColor != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:fillColor :" + id + " :" + fillColor.WriteOWL(writer) + ")");
            if (borderColor != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:borderColor :" + id + " :" + borderColor.WriteOWL(writer) + ")");
            if (borderThickness != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:borderThickness :" + id + " :" + borderThickness.WriteOWL(writer) + ")");
        }
    }

    enum FontStyle : byte
    {
        Plain = 0x00,
        Bold = 0x01,
        Italic = 0x02,
        Underline = 0x04
    }

    class Font
    {
        private ValueString name;
        private FontStyle style;
        private ValueInteger size;
        private ValueColor color;
        public Font(SyntaxTreeNode node, Variable variable)
        {
            if (node.Children.Count == 0) return;
            name = variable.GetValueString(node.Children[0]);
            style = FontStyle.Plain;
            size = variable.GetValueInteger(node.Children[2]);
            color = variable.GetValueColor(node.Children[3]);
            foreach (SyntaxTreeNode sn in node.Children[1].Children)
            {
                if (sn.Symbol.Name == "bold") style = style | FontStyle.Bold;
                else if (sn.Symbol.Name == "italic") style = style | FontStyle.Italic;
                else if (sn.Symbol.Name == "underline") style = style | FontStyle.Underline;
            }
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("font");
            writer.WriteLine("\tClassAssertion(cvssl:Font :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontName :" + id + " :" + name.WriteOWL(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontSize :" + id + " :" + size.WriteOWL(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontColor :" + id + " :" + color.WriteOWL(writer) + ")");
            if ((style & FontStyle.Bold) == FontStyle.Bold)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontStyles :" + id + " cvssl:bold)");
            if ((style & FontStyle.Bold) == FontStyle.Italic)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontStyles :" + id + " cvssl:italic)");
            if ((style & FontStyle.Bold) == FontStyle.Underline)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:fontStyles :" + id + " cvssl:underline)");
            return id;
        }
    }

    abstract class Element
    {
        public abstract string WriteOWL(System.IO.StreamWriter writer);
        public abstract void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered);
        public abstract void BuildASTPattern(ast.ASTPattern parent, bool maybe);

        protected void WriteOWL(System.IO.StreamWriter writer, Alignment alignment, string id)
        {
            string value = alignment.ToString();
            value = value[0].ToString().ToLower() + value.Substring(1);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:alignment :" + id + " :" + value + ")");
        }
    }

    class Rectangle : Element
    {
        private SizeInfo size;
        private DrawingInfo drawing;
        private ValueInteger rounding;
        public Rectangle(SyntaxTreeNode node, Variable variable)
        {
            size = new SizeInfo(node.Children[1], variable);
            drawing = new DrawingInfo(node.Children[2], variable);
            if (node.Children[0].Children.Count != 0)
                rounding = variable.GetValueInteger(node.Children[0].Children[0]);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("rectangle");
            writer.WriteLine("\tClassAssertion(cvssl:Rectangle :" + id + ")");
            size.WriteOWL(writer, id);
            drawing.WriteOWL(writer, id);
            if (rounding != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:roundSize :" + id + " :" + rounding.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered) { }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe) { }
    }

    class Ellipse : Element
    {
        private SizeInfo size;
        private DrawingInfo drawing;
        public Ellipse(SyntaxTreeNode node, Variable variable)
        {
            size = new SizeInfo(node.Children[0], variable);
            drawing = new DrawingInfo(node.Children[1], variable);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("ellipse");
            writer.WriteLine("\tClassAssertion(cvssl:Ellipse :" + id + ")");
            size.WriteOWL(writer, id);
            drawing.WriteOWL(writer, id);
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered) { }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe) { }
    }

    class Point
    {
        private ValueInteger x;
        private ValueInteger y;
        public Point(SyntaxTreeNode node, Variable variable)
        {
            x = variable.GetValueInteger(node.Children[0]);
            y = variable.GetValueInteger(node.Children[1]);
        }
        public string WriteOWL(System.IO.StreamWriter writer, int index)
        {
            string id = IDProvider.GetID("point");
            writer.WriteLine("\tClassAssertion(cvssl:Point :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:x :" + id + " :" + x.WriteOWL(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:y :" + id + " :" + y.WriteOWL(writer) + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:index :" + id + " " + index.ToString() + ")");
            return id;
        }
    }

    class Path : Element
    {
        private List<Point> points;
        private DrawingInfo drawing;
        public Path(SyntaxTreeNode node, Variable variable)
        {
            points = new List<Point>();
            foreach (SyntaxTreeNode pn in node.Children[0].Children)
                points.Add(new Point(pn, variable));
            drawing = new DrawingInfo(node.Children[1], variable);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("path");
            writer.WriteLine("\tClassAssertion(cvssl:Path :" + id + ")");
            for (int i = 0; i != points.Count; i++)
            {
                string pid = points[i].WriteOWL(writer, i);
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:points :" + id + " :" + pid + ")");
            }
            drawing.WriteOWL(writer, id);
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered) { }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe) { }
    }

    class Image : Element
    {
        private ValueString source;
        public Image(SyntaxTreeNode node, Variable variable)
        {
            source = variable.GetValueString(node.Children[0]);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("image");
            writer.WriteLine("\tClassAssertion(cvssl:Image :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:source :" + id + " :" + source.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered) { }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe) { }
    }

    class Label : Element
    {
        private SizeInfo size;
        private Font font;
        private ValueString text;
        public Label(SyntaxTreeNode node, Variable variable)
        {
            text = variable.GetValueString(node.Children[0]);
            size = new SizeInfo(node.Children[1], variable);
            if (node.Children[2].Children.Count != 0)
                font = new Font(node.Children[2], variable);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("label");
            writer.WriteLine("\tClassAssertion(cvssl:Label :" + id + ")");
            size.WriteOWL(writer, id);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:text :" + id + " :" + text.WriteOWL(writer) + ")");
            if (font != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:font :" + id + " :" + font.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered) { }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe) { }
    }

    enum DataPlaceholderType
    {
        String, Integer, Float, Boolean
    }

    class DataPlaceholder : Element
    {
        private DataPlaceholderType type;
        private SizeInfo size;
        private Font font;
        private string description;
        private string property;
        public DataPlaceholder(SyntaxTreeNode node, Variable variable)
        {
            if (node.Symbol.Name.EndsWith("s")) type = DataPlaceholderType.String;
            else if (node.Symbol.Name.EndsWith("i")) type = DataPlaceholderType.Integer;
            else if (node.Symbol.Name.EndsWith("f")) type = DataPlaceholderType.Float;
            else if (node.Symbol.Name.EndsWith("b")) type = DataPlaceholderType.Boolean;
            description = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            size = new SizeInfo(node.Children[1], variable);
            if (node.Children[2].Children.Count != 0)
                font = new Font(node.Children[2], variable);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("placeholder");
            writer.WriteLine("\tClassAssertion(cvssl:" + type.ToString() + "DataPlaceholder :" + id + ")");
            size.WriteOWL(writer, id);
            writer.WriteLine("\tDataPropertyAssertion(cvssl:description :" + id + " " + description + ")");
            if (font != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:font :" + id + " :" + font.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            property = MakeProperty();
            property = model.AddDataProperty(property, parent.Name, type.ToString().ToLower());
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            parent.AddChild(new ast.ASTPatternPlaceholder(type.ToString(), property));
        }
        private string MakeProperty()
        {
            System.Text.RegularExpressions.Regex pattern = new System.Text.RegularExpressions.Regex("(\\w|_)+");
            System.Text.RegularExpressions.MatchCollection matches = pattern.Matches(description);
            System.Text.StringBuilder builder = new StringBuilder("has");
            foreach (System.Text.RegularExpressions.Match match in matches)
                builder.Append(match.Value);
            return builder.ToString();
        }
    }

    enum ConnectorEndStyle
    {
        Link, Arrow, Diamond, Circle
    }

    class Node : VariableRef
    {
        private int max;
        private bool hasLimit;
        private List<string> ports;

        public Node(SyntaxTreeNode node, Variable variable, ViewDefinition view)
            : base(node, variable, view)
        {
            this.hasLimit = (node.Children[2].Children.Count != 0);
            if (hasLimit)
                this.max = int.Parse((node.Children[2].Children[0].Symbol as SymbolTokenText).ValueText);
            this.ports = new List<string>();
            foreach (SyntaxTreeNode pn in node.Children[3].Children)
                ports.Add((pn.Symbol as SymbolTokenText).ValueText);
        }

        public void Fill(Dictionary<string, List<Variable>> data)
        {
            foreach (string port in ports)
            {
                if (!data.ContainsKey(port))
                    data.Add(port, new List<Variable>());
                data[port].Add(variable);
            }
        }

        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("node");
            writer.WriteLine("\tClassAssertion(cvssl:Node :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:hasCardMax :" + id + " \"" + hasLimit + "\"^^xsd:boolean)");
            if (hasLimit)
                writer.WriteLine("\tDataPropertyAssertion(cvssl:cardMax :" + id + " " + max + ")");
            foreach (string port in ports)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:ports :" + id + " :" + port + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:variable :" + id + " :" + variable.Name + ")");
            foreach (Assign assign in values)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:assigns :" + id + " :" + assign.WriteOWL(writer) + ")");
            return id;
        }
    }

    class ConnectorPort
    {
        private string port;
        private int max;
        private bool hasLimit;

        public string Name { get { return port; } }

        public ConnectorPort(SyntaxTreeNode node)
        {
            this.port = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            this.hasLimit = (node.Children[1].Children.Count != 0);
            if (this.hasLimit)
                this.max = int.Parse((node.Children[1].Children[0].Symbol as SymbolTokenText).ValueText);
        }

        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("cport");
            writer.WriteLine("\tClassAssertion(cvssl:ConnectorPort :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:port :" + id + " :" + port + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:hasCardMax :" + id + " \"" + hasLimit + "\"^^xsd:boolean)");
            if (hasLimit)
                writer.WriteLine("\tDataPropertyAssertion(cvssl:cardMax :" + id + " " + max + ")");
            return id;
        }
    }

    class ConnectorEnd
    {
        private List<ConnectorPort> ports;
        private DrawingInfo drawing;
        private ConnectorEndStyle style;
        private Variable legend;

        public ICollection<ConnectorPort> Ports { get { return ports; } }
        public Variable Legend { get { return legend; } }

        public ConnectorEnd(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            ports = new List<ConnectorPort>();
            foreach (SyntaxTreeNode cn in node.Children[0].Children)
                ports.Add(new ConnectorPort(cn));
            if (node.Children[1].Children.Count != 0)
                legend = view.GetVariable((node.Children[1].Children[0].Symbol as SymbolTokenText).ValueText);
            if (node.Children[2].Symbol.Name == "link") style = ConnectorEndStyle.Link;
            else if (node.Children[2].Symbol.Name == "arrow") style = ConnectorEndStyle.Arrow;
            else if (node.Children[2].Symbol.Name == "diamond") style = ConnectorEndStyle.Diamond;
            else if (node.Children[2].Symbol.Name == "circle") style = ConnectorEndStyle.Circle;
            drawing = new DrawingInfo(node.Children[3], variable);
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("end");
            writer.WriteLine("\tClassAssertion(cvssl:ConnectorEnd :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:style :" + id + " :" + style.ToString().ToLower() + ")");
            if (legend != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:legend :" + id + " :" + legend.Name + ")");
            drawing.WriteOWL(writer, id);
            foreach (ConnectorPort port in ports)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:endPorts :" + id + " :" + port.WriteOWL(writer) + ")");
            return id;
        }
    }

    class Connector : Symbol
    {
        private string name;
        private ConnectorEnd origin;
        private ConnectorEnd target;
        private ValueColor linkColor;
        private ValueInteger linkThickness;
        private Variable legend;
        private bool built;
        private string property;
        private List<Variable> origins;
        private List<Variable> targets;

        public string Name { get { return name; } }

        public Connector(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            name = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            if (node.Children[1].Children.Count > 0)
            {
                linkColor = variable.GetValueColor(node.Children[1].Children[0]);
                if (node.Children[1].Children.Count > 1)
                    linkThickness = variable.GetValueInteger(node.Children[1].Children[1]);
            }
            if (node.Children[2].Children.Count != 0)
                legend = view.GetVariable((node.Children[2].Children[0].Symbol as SymbolTokenText).ValueText);
            origin = new ConnectorEnd(node.Children[3], variable, view);
            target = new ConnectorEnd(node.Children[4], variable, view);
            view.AddConnector(this);
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            writer.WriteLine("\tClassAssertion(cvssl:Connector :" + name + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:name :" + name + " \"" + name + "\")");
            if (linkColor != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:borderColor :" + name + " :" + linkColor.WriteOWL(writer) + ")");
            if (linkThickness != null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:borderThickness :" + name + " :" + linkThickness.WriteOWL(writer) + ")");
            if (legend!= null)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:legend :" + name + " :" + legend.Name + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:origin :" + name + " :" + origin.WriteOWL(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:target :" + name + " :" + target.WriteOWL(writer) + ")");
            return name;
        }

        public void LoadNodes(Dictionary<string, List<Variable>> data)
        {
            this.origins = new List<Variable>();
            this.targets = new List<Variable>();
            foreach (ConnectorPort port in origin.Ports)
            {
                foreach (Variable var in data[port.Name])
                    if (!this.origins.Contains(var))
                        this.origins.Add(var);
            }
            foreach (ConnectorPort port in target.Ports)
            {
                foreach (Variable var in data[port.Name])
                    if (!this.targets.Contains(var))
                        this.targets.Add(var);
            }
        }

        public void BuildDefaultModel(model.Model model, ViewDefinition view)
        {
            if (built) return;
            if (legend != null || origin.Legend != null || target.Legend != null)
                BuildDefaultModel_AssociationClass(model, view);
            else
                BuildDefaultModel_Relation(model);
            built = true;
        }
        private void BuildDefaultModel_AssociationClass(model.Model model, ViewDefinition view)
        {
            model.AddClass(name);
            foreach (Variable node in origins)
                model.AddObjProperty(name + "_origin", name, node.Name, true, false);
            foreach (Variable node in targets)
                model.AddObjProperty(name + "_target", name, node.Name, true, false);
            if (legend != null)
                legend.Definition.BuildDefaultModel(model, view, this, 1, 1, false);
            if (origin.Legend != null)
                origin.Legend.Definition.BuildDefaultModel(model, view, this, 1, 1, false);
            if (target.Legend != null)
                target.Legend.Definition.BuildDefaultModel(model, view, this, 1, 1, false);
        }
        private void BuildDefaultModel_Relation(model.Model model)
        {
            foreach (Variable no in origins)
            {
                foreach (Variable nt in targets)
                {
                    string temp = "link" + name;
                    if (property != null) temp = property;
                    temp = model.AddObjProperty(temp, no.Name, nt.Name, false, false);
                    if (property == null) property = temp;
                }
            }
        }
        
        public ast.ASTPattern BuildASTPattern()
        {
            ast.ASTPatternConnector node = new ast.ASTPatternConnector(name, property);
            if (legend != null) AddLegendNode(node, legend);
            if (origin.Legend != null) AddLegendNode(node, origin.Legend);
            if (target.Legend != null) AddLegendNode(node, target.Legend);
            return node;
        }
        private void AddLegendNode(ast.ASTPatternConnector root, Variable legend)
        {
            ast.ASTPattern ln = new ast.ASTPattern(legend.Name);
            root.AddChild(ln);
            legend.Definition.BuildASTPattern(ln, false);
        }
    }

    class Graph : Element
    {
        private List<Node> nodes;
        private List<Connector> connectors;

        public Graph(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            this.nodes = new List<Node>();
            this.connectors = new List<Connector>();
            foreach (SyntaxTreeNode cn in node.Children)
            {
                if (cn.Symbol.Name == "node")
                    this.nodes.Add(new Node(cn, variable, view));
                else
                    this.connectors.Add(new Connector(cn, variable, view));
            }
            Dictionary<string, List<Variable>> data = new Dictionary<string, List<Variable>>();
            foreach (Node cn in nodes)
                cn.Fill(data);
            foreach (Connector connector in connectors)
                connector.LoadNodes(data);
        }

        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("graph");
            writer.WriteLine("\tClassAssertion(cvssl:Graph :" + id + ")");
            foreach (Node node in nodes)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:nodes :" + id + " :" + node.WriteOWL(writer) + ")");
            foreach (Connector connector in connectors)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:connectors :" + id + " :" + connector.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            foreach (Node node in nodes)
                node.BuildDefaultModel(model, view, parent, min, max, ordered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            foreach (Node node in nodes)
                node.BuildASTPattern(parent, true);
        }
    }

    enum Alignment
    {
        Left, Right, Top, Bottom,
        Horizontal, Vertical,
        StackTopLeft, StackTop, StackTopRight,
        StackLeft, StackCenter, StackRight,
        StackBottomLeft, StackBottom, StackBottomRight
    }

    class Concat : Element
    {
        private List<Element> children;
        private bool isPacked;
        private Alignment alignment;
        public Concat(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            children = new List<Element>();
            foreach (SyntaxTreeNode cn in node.Children[0].Children)
                children.Add(view.GetElement(cn, variable));
            alignment = Alignment.Horizontal;
            isPacked = true;
            if (node.Children[1].Children.Count != 0)
            {
                if (node.Children[1].Children[0].Children.Count != 0)
                    isPacked = node.Children[1].Children[0].Children[0].Symbol.Name == "packed";
                if (node.Children[1].Children[1].Children.Count != 0)
                    alignment = variable.GetAlignment(node.Children[1].Children[1]);
            }
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("concat");
            writer.WriteLine("\tClassAssertion(cvssl:Concat :" + id + ")");
            WriteOWL(writer, alignment, id);
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isPacked :" + id + " \"" + isPacked.ToString().ToLower() + "\"^^xsd:boolean)");
            for (int i = 0; i != children.Count; i++)
            {
                string cid = children[i].WriteOWL(writer);
                string eid = IDProvider.GetID("celem");
                writer.WriteLine("\tClassAssertion(cvssl:ConcatElem :" + eid + ")");
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:element :" + eid + " :" + cid + ")");
                writer.WriteLine("\tDataPropertyAssertion(cvssl:index :" + eid + " " + i.ToString() + ")");
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:concatElems :" + id + " :" + eid + ")");
            }
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            foreach (Element elem in children)
                elem.BuildDefaultModel(model, view, parent, min, max, ordered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            foreach (Element elem in children)
                elem.BuildASTPattern(parent, maybe);
        }
    }

    class Union : Element
    {
        private List<Element> children;
        public Union(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            children = new List<Element>();
            foreach (SyntaxTreeNode child in node.Children)
                children.Add(view.GetElement(child, variable));
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("union");
            writer.WriteLine("\tClassAssertion(cvssl:Union :" + id + ")");
            foreach (Element child in children)
            {
                string cid = child.WriteOWL(writer);
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:elements :" + id + " :" + cid + ")");
            }
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            foreach (Element elem in children)
                elem.BuildDefaultModel(model, view, parent, min, max, ordered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            ast.ASTPatternChoice choice = new ast.ASTPatternChoice();
            parent.AddChild(choice);
            foreach (Element elem in children)
                elem.BuildASTPattern(choice, maybe);
        }
    }

    class Optional : Element
    {
        private Element child;
        public Optional(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            child = view.GetElement(node.Children[0], variable);
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("optional");
            writer.WriteLine("\tClassAssertion(cvssl:Optional :" + id + ")");
            string cid = child.WriteOWL(writer);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:element :" + id + " :" + cid + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            child.BuildDefaultModel(model, view, parent, 0, 1, ordered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            child.BuildASTPattern(parent, true);
        }
    }

    class ZeroMore : Element
    {
        private Element child;
        private bool isPacked;
        private bool isOrdered;
        private Alignment alignment;
        public ZeroMore(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            child = view.GetElement(node.Children[0], variable);
            isOrdered = (node.Children[1].Children.Count != 0);
            alignment = Alignment.Horizontal;
            isPacked = true;
            if (node.Children[2].Children.Count != 0)
            {
                if (node.Children[2].Children[0].Children.Count != 0)
                    isPacked = node.Children[2].Children[0].Children[0].Symbol.Name == "packed";
                if (node.Children[2].Children[1].Children.Count != 0)
                    alignment = variable.GetAlignment(node.Children[2].Children[1]);
            }
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("zeromore");
            writer.WriteLine("\tClassAssertion(cvssl:ZeroMore :" + id + ")");
            WriteOWL(writer, alignment, id);
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isPacked :" + id + " \"" + isPacked.ToString().ToLower() + "\"^^xsd:boolean)");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isOrdered :" + id + " \"" + isOrdered.ToString().ToLower() + "\"^^xsd:boolean)");
            string cid = child.WriteOWL(writer);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:element :" + id + " :" + cid + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            child.BuildDefaultModel(model, view, parent, 0, Int32.MaxValue, isOrdered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            child.BuildASTPattern(parent, true);
        }
    }

    class OneMore : Element
    {
        private Element child;
        private bool isPacked;
        private bool isOrdered;
        private Alignment alignment;
        public OneMore(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            child = view.GetElement(node.Children[0], variable);
            isOrdered = (node.Children[1].Children.Count != 0);
            alignment = Alignment.Horizontal;
            isPacked = true;
            if (node.Children[2].Children.Count != 0)
            {
                if (node.Children[2].Children[0].Children.Count != 0)
                    isPacked = node.Children[2].Children[0].Children[0].Symbol.Name == "packed";
                if (node.Children[2].Children[1].Children.Count != 0)
                    alignment = variable.GetAlignment(node.Children[2].Children[1]);
            }
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("onemore");
            writer.WriteLine("\tClassAssertion(cvssl:OneMore :" + id + ")");
            WriteOWL(writer, alignment, id);
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isPacked :" + id + " \"" + isPacked.ToString().ToLower() + "\"^^xsd:boolean)");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:isOrdered :" + id + " \"" + isOrdered.ToString().ToLower() + "\"^^xsd:boolean)");
            string cid = child.WriteOWL(writer);
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:element :" + id + " :" + cid + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            child.BuildDefaultModel(model, view, parent, 1, Int32.MaxValue, isOrdered);
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            child.BuildASTPattern(parent, true);
        }
    }

    class Assign
    {
        private Parameter parameter;
        private Value value;
        public Assign(Parameter param, Value value)
        {
            this.parameter = param;
            this.value = value;
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("assign");
            writer.WriteLine("\tClassAssertion(cvssl:Assign :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:parameter :" + id + " :" + parameter.WriteOWL(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:value :" + id + " :" + value.WriteOWL(writer) + ")");
            return id;
        }
        public void AddToAST(ast.ASTPattern node)
        {
            node.AddParameter(new ast.Parameter(parameter, value));
        }
    }

    class VariableRef : Element
    {
        protected Variable variable;
        protected List<Assign> values;
        protected string property;
        protected bool isOrdered;
        public VariableRef(SyntaxTreeNode node, Variable variable, ViewDefinition view)
        {
            this.variable = view.GetVariable((node.Children[0].Symbol as SymbolTokenText).ValueText);
            values = new List<Assign>();
            int index = 0;
            foreach (SyntaxTreeNode cn in node.Children[1].Children)
            {
                Value value = variable.GetValue(cn);
                values.Add(new Assign(this.variable.GetParameter(index), value));
                index++;
            }
        }
        public override string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("varref");
            writer.WriteLine("\tClassAssertion(cvssl:VariableRef :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:variable :" + id + " :" + variable.Name + ")");
            foreach (Assign assign in values)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:assigns :" + id + " :" + assign.WriteOWL(writer) + ")");
            return id;
        }
        public override void BuildDefaultModel(model.Model model, ViewDefinition view, Symbol parent, int min, int max, bool ordered)
        {
            if (view.IsModelClass(variable))
            {
                property = "has" + variable.Name;
                if (max > 1) property = model.GetPlural(property);
                property = model.AddObjProperty(property, parent.Name, variable.Name, (max <= 1), ordered);
                isOrdered = ordered;
            }
            else
            {
                variable.Definition.BuildDefaultModel(model, view, parent, min, max, ordered);
            }
        }
        public override void BuildASTPattern(ast.ASTPattern parent, bool maybe)
        {
            if (property != null)
            {
                ast.ASTPatternVariable node = new ast.ASTPatternVariable(variable.Name, property, isOrdered);
                parent.AddChild(node);
                foreach (Assign assign in values)
                    assign.AddToAST(node);
            }
            else
            {
                ast.ASTPattern node = new ast.ASTPattern(variable.Name);
                parent.AddChild(node);
                variable.Definition.BuildASTPattern(node, false);
                foreach (Assign assign in values)
                    assign.AddToAST(node);
            }
        }
    }

    class Variable : Symbol
    {
        private string name;
        private List<Parameter> listParams;
        private Dictionary<string, Parameter> parameters;
        private Element definition;
        private SyntaxTreeNode node;

        public string Name { get { return name; } }
        public Element Definition { get { return definition; } }

        public Variable(SyntaxTreeNode node)
        {
            name = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            parameters = new Dictionary<string, Parameter>();
            listParams = new List<Parameter>();
            foreach (SyntaxTreeNode pn in node.Children[1].Children)
            {
                Parameter param = new Parameter((pn.Symbol as SymbolTokenText).ValueText.Substring(1));
                listParams.Add(param);
                parameters.Add(param.Name, param);
            }
            this.node = node;
        }

        public Parameter GetParameter(SyntaxTreeNode node)
        {
            string name = (node.Symbol as SymbolTokenText).ValueText.Substring(1);
            return parameters[name];
        }
        public Parameter GetParameter(int index)
        {
            return listParams[index];
        }
        public Value GetValue(SyntaxTreeNode node)
        {
            if (node.Symbol.Name == "PARAMETER")
                return GetParameter(node);
            else if (node.Symbol.Name == "INTEGER")
                return new ConstantInteger(node);
            else if (node.Symbol.Name == "STRING")
                return new ConstantString(node);
            else if (node.Symbol.Name == "COLOR")
                return new ConstantColor(node);
            return null;
        }
        public ValueInteger GetValueInteger(SyntaxTreeNode node)
        {
            if (node.Symbol.Name == "PARAMETER")
                return GetParameter(node);
            return new ConstantInteger(node);
        }
        public ValueString GetValueString(SyntaxTreeNode node)
        {
            if (node.Symbol.Name == "PARAMETER")
                return GetParameter(node);
            return new ConstantString(node);
        }
        public ValueColor GetValueColor(SyntaxTreeNode node)
        {
            if (node.Symbol.Name == "PARAMETER")
                return GetParameter(node);
            return new ConstantColor(node);
        }

        public Alignment GetAlignment(SyntaxTreeNode node)
        {
            if (node.Children.Count == 0)
                return Alignment.Horizontal;
            if (node.Children[0].Symbol.Name != "stack")
            {
                if (node.Children[0].Symbol.Name == "top") return Alignment.Top;
                if (node.Children[0].Symbol.Name == "bottom") return Alignment.Bottom;
                if (node.Children[0].Symbol.Name == "left") return Alignment.Left;
                if (node.Children[0].Symbol.Name == "right") return Alignment.Right;
                if (node.Children[0].Symbol.Name == "horizontal") return Alignment.Horizontal;
                if (node.Children[0].Symbol.Name == "vertical") return Alignment.Vertical;
            }
            if (node.Children.Count == 1)
                return Alignment.StackCenter;
            if (node.Children.Count == 2)
            {
                if (node.Children[1].Symbol.Name == "center") return Alignment.StackCenter;
                if (node.Children[1].Symbol.Name == "left") return Alignment.StackLeft;
                if (node.Children[1].Symbol.Name == "right") return Alignment.StackRight;
                if (node.Children[1].Symbol.Name == "top") return Alignment.StackTop;
                if (node.Children[1].Symbol.Name == "bottom") return Alignment.StackBottom;
            }
            if (node.Children[1].Symbol.Name == "top")
            {
                if (node.Children[2].Symbol.Name == "left") return Alignment.StackTopLeft;
                if (node.Children[2].Symbol.Name == "right") return Alignment.StackTopRight;
            }
            if (node.Children[1].Symbol.Name == "bottom")
            {
                if (node.Children[2].Symbol.Name == "left") return Alignment.StackBottomLeft;
                if (node.Children[2].Symbol.Name == "right") return Alignment.StackBottomRight;
            }
            return Alignment.Horizontal;
        }

        public void Load(ViewDefinition view)
        {
            definition = view.GetElement(node.Children[2], this);
        }

        public string WriteOWL(System.IO.StreamWriter writer)
        {
            writer.WriteLine("\tClassAssertion(cvssl:Variable :" + name + ")");
            foreach (Parameter param in listParams)
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:parameters :" + name + " :" + param.WriteOWLDefinition(writer) + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:definition :" + name + " :" + definition.WriteOWL(writer) + ")");
            return name;
        }

        public void BuildDefaultModel(model.Model model, ViewDefinition view) { model.AddClass(name); }

        public ast.ASTPattern BuildASTPattern()
        {
            ast.ASTPattern node = new ast.ASTPattern(name);
            definition.BuildASTPattern(node, false);
            return node;
        }
    }

    class ToolboxElement
    {
        private Symbol symbol;
        private string description;
        private string icon;
        public ToolboxElement(SyntaxTreeNode node, ViewDefinition view)
        {
            symbol = view.GetSymbol((node.Children[0].Symbol as SymbolTokenText).ValueText);
            description = (node.Children[1].Symbol as SymbolTokenText).ValueText;
            if (node.Children.Count > 2)
                icon = (node.Children[2].Symbol as SymbolTokenText).ValueText;
        }
        public bool IsMatch(Symbol symbol) { return (this.symbol == symbol); }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("tbe");
            writer.WriteLine("\tClassAssertion(cvssl:ToolboxElement :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:symbol :" + id + " :" + symbol.Name + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:description :" + id + " " + description + ")");
            if (icon != null)
                writer.WriteLine("\tDataPropertyAssertion(cvssl:icon :" + id + " " + icon + ")");
            return id;
        }
        public void BuildDefaultModel(model.Model model, ViewDefinition view) { symbol.BuildDefaultModel(model, view); }
    }

    class Toolbox
    {
        private string description;
        private List<ToolboxElement> elements;
        public Toolbox(SyntaxTreeNode node, ViewDefinition view)
        {
            description = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            elements = new List<ToolboxElement>();
            foreach (SyntaxTreeNode cn in node.Children[1].Children)
                elements.Add(new ToolboxElement(cn, view));
        }
        public bool IsMatch(Symbol symbol)
        {
            foreach (ToolboxElement elem in elements)
                if (elem.IsMatch(symbol))
                    return true;
            return false;
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("tb");
            writer.WriteLine("\tClassAssertion(cvssl:Toolbox :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:description :" + id + " " + description + ")");
            for (int i = 0; i != elements.Count; i++)
            {
                string tbeid = elements[i].WriteOWL(writer);
                writer.WriteLine("\tDataPropertyAssertion(cvssl:index :" + tbeid + " " + i.ToString() + ")");
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:components :" + id + " :" + tbeid + ")");
            }
            return id;
        }
        public void BuildDefaultModel(model.Model model, ViewDefinition view)
        {
            foreach (ToolboxElement elem in elements)
                elem.BuildDefaultModel(model, view);
        }
    }

    class Library
    {
        private Symbol symbol;
        private string description;
        public Library(SyntaxTreeNode node, ViewDefinition view)
        {
            symbol = view.GetSymbol((node.Children[0].Symbol as SymbolTokenText).ValueText);
            description = (node.Children[1].Symbol as SymbolTokenText).ValueText;
        }
        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("lib");
            writer.WriteLine("\tClassAssertion(cvssl:Library :" + id + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:symbol :" + id + " :" + symbol.Name + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:description :" + id + " " + description + ")");
            return id;
        }
        public bool IsMatch(Symbol symbol) { return (this.symbol == symbol); }
        public void BuildDefaultModel(model.Model model, ViewDefinition view) { symbol.BuildDefaultModel(model, view); }
    }

    class ViewDefinition
    {
        private string description;
        private Variable axiom;
        private List<Toolbox> toolboxes;
        private List<Library> libraries;
        private Dictionary<string, Variable> variables;
        private Dictionary<string, Connector> connectors;

        public ViewDefinition(SyntaxTreeNode node)
        {
            description = (node.Children[0].Symbol as SymbolTokenText).ValueText;
            toolboxes = new List<Toolbox>();
            libraries = new List<Library>();
            variables = new Dictionary<string, Variable>();
            connectors = new Dictionary<string, Connector>();
            foreach (SyntaxTreeNode rn in node.Children[1].Children[1].Children)
            {
                Variable var = new Variable(rn);
                variables.Add(var.Name, var);
            }
            foreach (Variable var in variables.Values)
                var.Load(this);
            foreach (SyntaxTreeNode tn in node.Children[2].Children)
                toolboxes.Add(new Toolbox(tn, this));
            foreach (SyntaxTreeNode ln in node.Children[3].Children)
                libraries.Add(new Library(ln, this));
            axiom = variables[(node.Children[1].Children[0].Symbol as SymbolTokenText).ValueText];
        }

        public Symbol GetSymbol(string name)
        {
            if (variables.ContainsKey(name))
                return variables[name];
            return connectors[name];
        }
        public Variable GetVariable(string name) { return variables[name]; }
        public ICollection<Variable> GetVariables(string pattern)
        {
            List<Variable> result = new List<Variable>();
            System.Text.RegularExpressions.Regex regexp = new System.Text.RegularExpressions.Regex(pattern);
            foreach (string var in variables.Keys)
            {
                System.Text.RegularExpressions.Match match = regexp.Match(var);
                if (match.Length == var.Length)
                    result.Add(variables[var]);
            }
            return result;
        }
        public void AddConnector(Connector connector) { connectors.Add(connector.Name, connector); }

        public bool IsModelClass(Symbol symbol)
        {
            foreach (Toolbox elem in toolboxes)
                if (elem.IsMatch(symbol))
                    return true;
            foreach (Library elem in libraries)
                if (elem.IsMatch(symbol))
                    return true;
            return false;
        }

        public Element GetElement(SyntaxTreeNode node, Variable variable)
        {
            switch (node.Symbol.Name)
            {
                case "rectangle": return new Rectangle(node, variable);
                case "ellipse": return new Ellipse(node, variable);
                case "path": return new Path(node, variable);
                case "image": return new Image(node, variable);
                case "label": return new Label(node, variable);
                case "placeholder_s": return new DataPlaceholder(node, variable);
                case "placeholder_d": return new DataPlaceholder(node, variable);
                case "placeholder_f": return new DataPlaceholder(node, variable);
                case "placeholder_b": return new DataPlaceholder(node, variable);
                case "graph": return new Graph(node, variable, this);
                case "concat": return new Concat(node, variable, this);
                case "optional": return new Optional(node, variable, this);
                case "zeromore": return new ZeroMore(node, variable, this);
                case "onemore": return new OneMore(node, variable, this);
                case "union": return new Union(node, variable, this);
                case "variable_ref": return new VariableRef(node, variable, this);
            }
            return null;
        }

        public string WriteOWL(System.IO.StreamWriter writer)
        {
            string id = IDProvider.GetID("view");
            writer.WriteLine("\tClassAssertion(cvssl:ViewDefinition :" + id + ")");
            writer.WriteLine("\tDataPropertyAssertion(cvssl:description :" + id + " " + description + ")");
            writer.WriteLine("\tObjectPropertyAssertion(cvssl:axiom :" + id + " :" + axiom.Name + ")");
            for (int i = 0; i != toolboxes.Count; i++)
            {
                string tbeid = toolboxes[i].WriteOWL(writer);
                writer.WriteLine("\tDataPropertyAssertion(cvssl:index :" + tbeid + " " + i.ToString() + ")");
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:toolboxes :" + id + " :" + tbeid + ")");
            }
            for (int i = 0; i != libraries.Count; i++)
            {
                string tbeid = libraries[i].WriteOWL(writer);
                writer.WriteLine("\tDataPropertyAssertion(cvssl:index :" + tbeid + " " + i.ToString() + ")");
                writer.WriteLine("\tObjectPropertyAssertion(cvssl:libraries :" + id + " :" + tbeid + ")");
            }
            foreach (Variable var in variables.Values)
                var.WriteOWL(writer);
            return id;
        }

        public void BuildDefaultModel(model.Model model)
        {
            /*
             * For all variables in toolboxes
             *      => Create new class
             *      
             * For all connectors in toolboxes
             *      If connector has a legend or one of its connector has a legend
             *          => Create a new association class
             *              Class ConnectorName
             *              ConnectorName_origin : ConnectorName -> UnionOf(origins)
             *              ConnectorName_target : ConnectorName -> UnionOf(targets)
             *              has[LegendName] : ConnectorName -> ConnectorLegend
             *              has[LeftLegendName] : ConnectorName -> LeftConnectorLegend
             *              has[RightLegendName] : ConnectorName -> RightConnectorLegend
             *      Else
             *          => Create a new property
             *              ConnectorName : UnionOf(origins) -> UnionOf(targets)
             * 
             * DataPlaceholder in a rule with root Variable
             *      => Create data property
             *          has[Description] : Variable -> [Type]
             * 
             * VariableRef in a rule with root Variable
             *      => Create object property
             *          has[RefName] : Variable -> [RefName]
             */
            foreach (Toolbox toolbox in toolboxes)
                toolbox.BuildDefaultModel(model, this);
            foreach (Library lib in libraries)
                lib.BuildDefaultModel(model, this);
            foreach (Variable var in variables.Values)
                if (var != axiom && IsModelClass(var))
                    var.Definition.BuildDefaultModel(model, this, var, 1, 1, false);
            axiom.Definition.BuildDefaultModel(model, this, axiom, 1, 1, false);
        }

        public void BuildTransformation(transform.Transformation transfo)
        {
            Dictionary<string, ast.ASTPattern> patterns = new Dictionary<string, ast.ASTPattern>();
            foreach (Variable var in variables.Values)
                if (var != axiom && IsModelClass(var))
                    patterns.Add(var.Name, var.BuildASTPattern());
            patterns.Add(axiom.Name, axiom.BuildASTPattern());
            foreach (Connector connector in connectors.Values)
                patterns.Add(connector.Name, connector.BuildASTPattern());
            foreach (ast.ASTPattern ast in patterns.Values)
                ast.BuildRoutes();
            transfo.Build(patterns);
        }
    }
}
